package cn.mw.cmdb.template.service;

import cn.mw.cmdb.template.entity.export.*;
import cn.mw.microMonitorCommon.util.ListMapObjUtils;
import com.alibaba.excel.annotation.ExcelProperty;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * @author gengjb
 * @description 模板配置导出管理
 * @date 2024/9/4 10:07
 */
@Component
@Slf4j
public class TemplateConfigurationExportManager {

    private final String TEMPLATE_INFO = "模板信息";
    private final String HOST_INFO = "主机信息";
    private final String MONITOR_ITEM_INFO = "监控项信息";
    private final String TRIGGER_INFO = "触发器信息";
    private final String DISCOVER_INFO = "自动发现信息";

    public void exportTemplate(List<TemplateExportDto> templateExportDtos, HttpServletResponse response) throws Exception{
        Workbook workbook = new XSSFWorkbook();
        OutputStream outputStream = null;
        try {
            for (TemplateExportDto templateExportDto : templateExportDtos) {
                String sheetName = templateExportDto.getName();
                if(StringUtils.isNotEmpty(templateExportDto.getName()) && (templateExportDto.getName().contains("[") || templateExportDto.getName().contains("]"))){
                    sheetName = templateExportDto.getName().replace("[","_");
                    sheetName = sheetName.replace("]","");
                }
                // 创建一个新的工作表
                Sheet sheet = workbook.createSheet(sheetName);
                Row mergedRow = sheet.createRow(0);
                Cell mergedCell = mergedRow.createCell(0);
                mergedCell.setCellValue(TEMPLATE_INFO);
                // 将样式应用到合并的单元格
                mergedCell.setCellStyle(styleSet(workbook));
                // 合并前两行的单元格
                sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 500));
                //设置模板数据
                Map<String, String> titleInfo = getTitleInfo(TemplateExportDto.class);
                setTemplateData(workbook,sheet, Arrays.asList(templateExportDto),titleInfo);
            }
            outputStream = setExcelHeaderInfo(response);
            workbook.write(outputStream);
        }catch (Throwable e){
            log.error("TemplateConfigurationExportManager{} exportTemplate() error",e);
        }finally {
            if(response != null){
                workbook.close();
            }
            if(outputStream != null){
                outputStream.close();
            }
        }



    }


    private void setTemplateData(Workbook workbook,Sheet sheet,List<TemplateExportDto> templateExportDtos,Map<String, String> titleMap){
        int row = 2;
        List<Map> templateData = ListMapObjUtils.objectsToMaps(templateExportDtos);
        Map<Integer, Row> rowMap = createRowInfo(templateData, row, sheet);
        row = setData(sheet,row,titleMap,templateData,rowMap,workbook);
        //设置主机数据
        List<HostExportDto> hosts = templateExportDtos.get(0).getHosts();
        row = mergedRow(sheet,row,workbook,HOST_INFO);
        titleMap = getTitleInfo(HostExportDto.class);
        List<Map> hostData = ListMapObjUtils.objectsToMaps(hosts);
        rowMap = createRowInfo(hostData, row, sheet);
        row = setData(sheet,row,titleMap,hostData,rowMap,workbook);
        //设置监控项数据
        List<MonitorItemExportDto> items = templateExportDtos.get(0).getItems();
        row = mergedRow(sheet,row,workbook,MONITOR_ITEM_INFO);
        titleMap = getTitleInfo(MonitorItemExportDto.class);
        List<Map> itemData = ListMapObjUtils.objectsToMaps(items);
        rowMap = createRowInfo(itemData, row, sheet);
        row = setData(sheet,row,titleMap,itemData,rowMap,workbook);
        //设置触发器数据
        List<TriggerExportDto> triggers = templateExportDtos.get(0).getTriggers();
        row = mergedRow(sheet,row,workbook,TRIGGER_INFO);
        titleMap = getTitleInfo(TriggerExportDto.class);
        List<Map> triggerData = ListMapObjUtils.objectsToMaps(triggers);
        rowMap = createRowInfo(triggerData, row, sheet);
        row = setData(sheet,row,titleMap,triggerData,rowMap,workbook);
        //设置自动发现数据
        List<DiscoverRuleExportDto> discoveries = templateExportDtos.get(0).getDiscoveries();
        row = mergedRow(sheet,row,workbook,DISCOVER_INFO);
        titleMap = getTitleInfo(DiscoverRuleExportDto.class);
        List<Map> discoverData = ListMapObjUtils.objectsToMaps(discoveries);
        rowMap = createRowInfo(discoverData, row, sheet);
        row = setData(sheet,row,titleMap,discoverData,rowMap,workbook);
    }


    private Map<Integer,Row> createRowInfo(List<Map> realData,int row,Sheet sheet){
        Map<Integer,Row> rowMap = new HashMap<>();
        for (int i = row+2; i <= realData.size()+row+2; i++) {
            Row bodyRow = sheet.createRow(i);
            rowMap.put(i,bodyRow);
        }
        return rowMap;
    }

    private int mergedRow(Sheet sheet,int row,Workbook workbook,String name){
        Row mergedRow = sheet.createRow(row+2);
        Cell mergedCell = mergedRow.createCell(0);
        mergedCell.setCellValue(name);
        // 将样式应用到合并的单元格
        mergedCell.setCellStyle(styleSet(workbook));
        // 合并前两行的单元格
        sheet.addMergedRegion(new CellRangeAddress(row+2, row+3, 0, 500));
        return row+3;
    }

    private Integer setData(Sheet sheet,int row,Map<String, String> titleMap,List<Map> realData,Map<Integer,Row> rowMap,Workbook workbook){
        row += 1;
        Row headerRow = sheet.createRow(row);
        int cellCount = 0;
        for (String key : titleMap.keySet()) {
            Cell cell = headerRow.createCell(cellCount);
            cell.setCellValue(titleMap.get(key));
            int dataRow = row+1;
            for (Map datum : realData) {
                Object o = datum.get(key);
                Row row1 = rowMap.get(dataRow);
                Cell cell1 = row1.createCell(cellCount);
                sheet.setColumnWidth(cellCount,40*256);
                if(o != null){
                    cell1.setCellValue(o.toString());
                    CellStyle cellStyle = workbook.createCellStyle();
                    cellStyle.setWrapText(true);
//                    cellStyle.setAlignment(HorizontalAlignment.CENTER);
//                    cellStyle.setVerticalAlignment(VerticalAlignment.);
                    cell1.setCellStyle(cellStyle);
                }
                dataRow++;
            }
            cellCount++;
        }
        row=row+realData.size()+1;
        return row;
    }

    private CellStyle styleSet(Workbook workbook){
        // 设置字体样式
        Font headerFont = workbook.createFont();
        headerFont.setBold(true); // 加粗
        headerFont.setFontHeightInPoints((short) 12); // 字体大小
        // 创建单元格样式并应用字体样式
        CellStyle headerCellStyle = workbook.createCellStyle();
        headerCellStyle.setAlignment(HorizontalAlignment.LEFT); // 水平左对齐
        headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        headerCellStyle.setFont(headerFont);
        return headerCellStyle;
    }

    public Map<String,String> getTitleInfo(Class cls){
        Map<String,String> titleMap = new LinkedHashMap<>();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            if(field.isAnnotationPresent(ExcelProperty.class)){
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                String[] value = excelProperty.value();
                String name = field.getName();
                titleMap.put(name,String.join(",",value));
            }
        }
        return titleMap;
    }


    private OutputStream setExcelHeaderInfo(HttpServletResponse response) throws Exception {
        Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        String fileName = milliSecond + ".xlsx";
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        OutputStream outputStream = response.getOutputStream();
        return outputStream;
    }
}
